package com.eric.demo.file;

import com.google.common.base.Charsets;
import com.google.common.io.Files;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

/**
 * @author ZhangGuangyin on 2018/8/23
 */
public class BigFileRead {

    /**
     * 使用文件流read()方式, 边读边用
     * @param file
     */
    public void method1(String file) throws Exception {
        BufferedInputStream reader = new BufferedInputStream(new FileInputStream(file), 8192);
        int bytes = -1;
        File file1 = new File("D:\\test\\insert1.sql");
        file1.createNewFile();
        do{
            byte[] array = new byte[8192];
            bytes = reader.read(array);
            if(bytes != -1){
                //做事情
                Files.append(new String(array), file1, Charsets.UTF_8);
            }
        }while (bytes > 0);
        reader.close();
    }

    /**
     * 使用NIO FileChannel
     * @param file
     */
    public void method2(String file) throws Exception {
        FileInputStream fileInputStream = new FileInputStream(file);
        ByteBuffer byteBuffer = ByteBuffer.allocate(65535);
        FileChannel fileChannel = fileInputStream.getChannel();
        int bytes = -1;
        File file2 = new File("D:\\test\\insert2.sql");
        file2.createNewFile();
        do{
            bytes = fileChannel.read(byteBuffer);
            if(bytes != -1){
                byte[] array = new byte[bytes];
                byteBuffer.flip();
                byteBuffer.get(array);
                byteBuffer.clear();

                //做事情
                Files.append(new String(array), file2, Charsets.UTF_8);
            }
        }while (bytes > 0);
        byteBuffer.clear();
        fileChannel.close();
        fileInputStream.close();
    }

    /**
     * 内存文件映射，就是把文件内容映射到虚拟内存的一块区域
     * @param file
     */
    public void method3(String file) throws Exception {
        FileInputStream fileInputStream = new FileInputStream(file);
        FileChannel fileChannel = fileInputStream.getChannel();
        MappedByteBuffer mappedBuf = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size() );
        boolean end = false;
        File file3 = new File("D:\\test\\insert3.sql");
        file3.createNewFile();
        do{
            int limit = mappedBuf.limit();
            int position = mappedBuf.position();
            if (position >= limit){
                end = true;
            }
            int maxSize = 2048;
            if(limit - position < maxSize){
                maxSize = limit - position;
            }
            byte[] array = new byte[maxSize];
            mappedBuf.get(array);

            //做事情
            Files.append(new String(array), file3, Charsets.UTF_8);
        }while (!end);

        mappedBuf.clear();
        fileChannel.close();
        fileInputStream.close();
    }

    public static void main(String[] argvs) throws Exception {
        String file = "D:\\test\\insert.sql";
        BigFileRead bigFileRead = new BigFileRead();
        long time1 = System.currentTimeMillis();
        bigFileRead.method1(file);
        long time2 = System.currentTimeMillis();
        System.out.println("method1 time:" + (time2 - time1));
        bigFileRead.method2(file);
        long time3 = System.currentTimeMillis();
        System.out.println("method2 time:" + (time3 - time2));
        bigFileRead.method3(file);
        long time4 = System.currentTimeMillis();
        System.out.println("method3 time:" + (time4 - time3));
    }


}
